import { unionBy } from 'lodash';
import {
	IAgentJoin,
	IAgentLeave,
	ICustomerJoin,
	ICustomerLeave,
	IRobotMembers,
	IStream,
	ISystemRecordPoint,
	IUserData,
	StreamAdd,
	StreamEnd,
	ICollectionVariable,
	IResponseVariable,
	ITestimonyBoardId,
	IAcceptCallMode,
	ITicketInfo,
	ICallProgressGroups,
	ISessionEventKey,
	IJoinedMembers,
	IRecordingPoint,
	IVariableList,
	IRoleWithBusiness,
	IRecordingAlert
	// IUpgradeData
} from './interface';
import Logger from '@/utils/Logger';

import {
	systemErrorEvent,
	ccsError,
	onDrop,
	onRing,
	onCancelRing,
	onAgentJoinSession,
	onAgentQuitSession,
	onCcsDrop,
	onCustomerJoinSession,
	onCustomerQuitSession,
	onStreamAdd,
	onStreamEnd,
	onTextMessage,
	onCustomizeMessage,
	onResourceMessage,
	removeSessionEvent,
	onAmsConnectStatus,
	onOtherReconnecting,
	onOtherResumeConnect,
	onRenderMediaStatus,
	onPublishMediaStatus,
	onSessionConnectStatus,
	onInvitationProgress,
	onVariableChange,
	onResetStatus,
	onSyncMessage,
	onRealTimeQuality,
	onUpgrade,
	onCcsResumeSuccess,
	onSessionRecordCrash,
	onSystemRecordUpdate,
	onSyncSessionSummary
} from './IVCS';

import Operation from './Operation';
import { filterMembers, filterStreamInfo, isAgentStream, isAudioStream, isCustomerStream, isRecordHiddenScreenStream, isScreenStream, isTTSstream, memberJoinSession } from './utils';
import MediaStreamDao from './dao/MediaStreamDao';
import StreamInfo from './libs/StreamInfo';
import clog from './CLog';

class Session extends Operation {
	public sessionId: string;
	public invitationId: string;
	public roomId: string;
	public publicationId: string;
	public bizScenarioId: string;
	public participantId: string;
	public recordingId: string;
	public roomToken: string;
	public clientID: string;
	public recordingPoint: IRecordingPoint;
	public recordingAlert: IRecordingAlert;
	public isIMSession: boolean;

	public systemRecordPoint: ISystemRecordPoint | null;
	public agentRecord: null;
	public agentStreams: IStream[];
	public userData: IUserData | null;
	public robotMembers: IRobotMembers[];
	public sessionMembers: IJoinedMembers[];
	public collectionVariable: ICollectionVariable[];
	public responseVariabelData: IResponseVariable[];
	public transcriptData: any[];
	public whiteboardId: string;
	public pdfWhiteBoardId: string;
	public TestimonyWriteBoardId: ITestimonyBoardId[];
	public acceptCallMode: IAcceptCallMode;
	public callProgress: number;
	public callProgressTime: any;
	public callProgressGroups: ICallProgressGroups[];
	public missCallTimer: number;
	public missCall: any;
	public missCallQuene: Map<string, any>;
	public ticketInfo: ITicketInfo;
	public audioStreams: IStream[];
	public customerStreams: IStream[];
	public allMediaStream: IStream[];
	public TTSstream: IStream[];
	public screenStreams: IStream[];
	public recordStreams: IStream[];
	public smallStreams: IStream[];
	public largeStreams: IStream[]; // 访客大窗口视频流
	public currentAgentStream: IStream | null;
	public renderedStreamMap: Map<string, MediaStream>;

	public errorView: boolean;
	public businessVariableList: IVariableList[];
	public customerVariableList: IVariableList[];
	public allRoleWihtBusiness: IRoleWithBusiness[];
	public mediaStreamDao: MediaStreamDao;
	// public upgradeData: IUpgradeData | null;
	public isAutoSystemRecord: boolean;
	public hasUnfinishedSummary: boolean; // 未完成的会话小结数量
	public lastSessionId: string; // 上一个会话id
	public lastSceneId: string;	// 上一个场景id

	public systemErrorEvent: (error: any) => void;
	public onCustomerJoinSession: (info: any) => void;
	public onCustomerQuitSession: (info: any) => void;
	public onAgentQuitSession: (info: any) => void;
	public onAgentJoinSession: (info: any) => void;
	public onStreamAdd: (stream: any) => void;
	public onStreamEnd: (stream: any) => void;
	public onCcsDrop: (resp: any) => void;
	public ccsError: (error: any) => void;
	public amsConnect: (status: any) => void;
	public onOtherReconnecting: (ack: any) => void;
	public onOtherResumeConnect: (ack: any) => void;
	public onDrop: (ack: any) => void;
	public onRing: (ack: any) => void;
	public onCancelRing: (ack: any) => void;
	public onRenderMediaStatus: (ack: any) => void;
	public onPublishMediaStatus: (ack: any) => void;
	public onSessionConnectStatus: (ack: any) => void;
	public onTextMessage: (ack: any) => void;
	public onCustomizeMessage: (ack: any) => void;
	public onResourceMessage: (ack: any) => void;
	public onInvitationProgress: (ack: any) => void;
	public onVariableChange: (ack: any) => void;
	public onResetStatus: (ack: any) => void;
	public onSyncMessage: (ack: any) => void;
	public onRealTimeQuality: (ack: any) => void;
	public onUpgrade: (ack: any) => void;
	public onCcsResumeSuccess: (ack: any) => void;
	public onSessionRecordCrash: (ack: any) => void;
	public onSystemRecordUpdate: (ack: any) => void;
	public onSyncSessionSummary: (ack: any) => void;

	public eventsMap: Map<string, void>;

	constructor() {
		super();
		this.sessionId = '';
		this.invitationId = '';
		this.bizScenarioId = '';
		this.participantId = '';
		this.publicationId = '';
		this.recordingId = '';
		this.roomId = '';
		this.roomToken = '';
		this.clientID = '';
		this.isIMSession = false;
		this.recordingAlert = {
			systemRecordingId: 0,
			screenRecordingId: 0,
			regionalScreenRecordingId: 0
		};

		this.systemRecordPoint = null;
		this.agentRecord = null;
		this.agentStreams = [];
		this.audioStreams = [];
		this.customerStreams = [];
		this.screenStreams = [];
		this.recordStreams = [];
		this.largeStreams = [];
		this.allMediaStream = [];
		this.TTSstream = [];
		this.smallStreams = [];
		this.currentAgentStream = null;

		this.renderedStreamMap = new Map();

		this.userData = null;
		this.robotMembers = [];
		this.sessionMembers = [];
		this.collectionVariable = [];
		this.transcriptData = [];
		this.responseVariabelData = [];
		this.whiteboardId = '';
		this.pdfWhiteBoardId = '';
		this.TestimonyWriteBoardId = [];
		this.callProgress = 0;
		this.callProgressTime = null;
		this.callProgressGroups = [];
		this.missCallQuene = new Map();
		this.missCallTimer = 0;
		this.ticketInfo = {
			agentId: '',
			refersh_ticket_time: 0,
			ticket: ''
		};

		this.acceptCallMode = {
			callMediaType: 'video',
			receiveMediaType: 'video',
			microphoneStatus: 'unmute'
		};

		this.recordingPoint = {
			userId: -1,
			userName: '',
			userRole: '',
			recordingId: '',
			content: '',
			timePoint: 0
		};

		this.errorView = false;

		this.businessVariableList = [];
		this.customerVariableList = [];
		this.allRoleWihtBusiness = [];

		this.isAutoSystemRecord = true; // 是否自动录制
		this.hasUnfinishedSummary = false; // 未完成的会话小结数量
		this.lastSessionId = ''; // 上一个会话id
		this.lastSceneId = ''; // 上一个场景id

		// this.upgradeData = null;

		this.systemErrorEvent = systemErrorEvent;
		this.onCustomerJoinSession = onCustomerJoinSession;
		this.onCustomerQuitSession = onCustomerQuitSession;
		this.onAgentJoinSession = onAgentJoinSession;
		this.onAgentQuitSession = onAgentQuitSession;
		this.onStreamAdd = onStreamAdd;
		this.onStreamEnd = onStreamEnd;
		this.ccsError = ccsError;
		this.onCcsDrop = onCcsDrop;
		this.amsConnect = onAmsConnectStatus;
		this.onOtherReconnecting = onOtherReconnecting;
		this.onDrop = onDrop;
		this.onRing = onRing;
		this.onTextMessage = onTextMessage;
		this.onCustomizeMessage = onCustomizeMessage;
		this.onResourceMessage = onResourceMessage;
		this.onCancelRing = onCancelRing;
		this.onOtherResumeConnect = onOtherResumeConnect;
		this.onRenderMediaStatus = onRenderMediaStatus;
		this.onPublishMediaStatus = onPublishMediaStatus;
		this.onSessionConnectStatus = onSessionConnectStatus;
		this.onInvitationProgress = onInvitationProgress;
		this.onResetStatus = onResetStatus;
		this.onVariableChange = onVariableChange;
		this.onSyncMessage = onSyncMessage;
		this.onRealTimeQuality = onRealTimeQuality;
		this.onUpgrade = onUpgrade;
		this.onCcsResumeSuccess = onCcsResumeSuccess;
		this.onSessionRecordCrash = onSessionRecordCrash;
		this.onSystemRecordUpdate = onSystemRecordUpdate;
		this.onSyncSessionSummary = onSyncSessionSummary;
		this.eventsMap = new Map();
		this.mediaStreamDao = new MediaStreamDao();
	}

	//设置是否为IM会话
	public setIsIMSession(isIMSession: boolean) {
		this.isIMSession = isIMSession;
	}

	//设置录像错误弹窗
	public setRecordingAlert(data: IRecordingAlert) {
		this.recordingAlert = { ...this.recordingAlert, ...data };
	}

	//设置当前业务场景所有访客角色
	public setAllRoleWithBusiness(data: IRoleWithBusiness[]) {
		this.allRoleWihtBusiness = [...this.allRoleWihtBusiness, ...data];
	}

	//设置客户信息变量
	public setCustomerVariableList(data: IVariableList[]) {
		this.customerVariableList = unionBy(data, this.customerVariableList, 'id');
	}

	public clearBusinessVariableList() {
		this.businessVariableList = [];
	}

	public clearCustomerVariableList() {
		this.customerVariableList = [];
	}

	//设置业务信息变量
	public setBusinessVariableList(data: IVariableList[]) {
		this.businessVariableList = unionBy(data, this.businessVariableList, 'id');
	}

	//设置错误蒙层
	public setErrorView(visible: boolean) {
		this.errorView = visible;
	}

	/** 新流加入 */
	public onStreamAddEvent = (streamData: IStream) => {
		this.setMediaStream(streamData);
		this.saveCurrentAgentStream();
	};

	/** 流离开 */
	public onStreamEndEvent = (stream: IStream) => {
		try {
			this.removeMediaStream(stream);
			Logger.info(`onStreamEndEvent:`, stream);
		} catch (error) {
			Logger.error(`onStreamEndEvent:`, error);
		}
	};

	/** 访客退出会话 */
	public onCustomerQuitSessionEvent = (streamData: ICustomerLeave) => {
		this.removeMediaStreamByClientId(streamData.data.id);
		Logger.info(`onCustomerQuitSessionEvent:`, streamData);
	};

	/** 访客加入会话 */
	public onCustomerJoinSessionEvent = (streamData: ICustomerJoin) => {
		Logger.info(`onCustomerJoinSessionEvent:`, streamData);
	};

	/** 坐席加入会话 */
	public onAgentJoinSessionEvent = (streamData: IAgentJoin) => {
		Logger.info(`onAgentJoinSessionEvent:`, streamData);
		this.updateIsRobot(streamData.data.id, streamData.data.user.profile.isRobot);
		this.setRobotMembers(streamData);
	};

	/** 坐席退出会话 */
	public onAgentQuitSessionEvent = (streamData: IAgentLeave) => {
		this.removeMediaStreamByClientId(streamData.data.id);
		Logger.info(`onAgentQuitSessionEvent:`, streamData);
	};

	/** 设置录屏参数 */
	public setSystemRecordPoint = (systemRecordPoint: ISystemRecordPoint) => {
		this.systemRecordPoint = { ...this.systemRecordPoint, ...systemRecordPoint };
		Logger.info(`setSystemRecordPoint:`, this.systemRecordPoint);
	};

	/**设置会话id */
	public setSessionId = (sessionId: string) => {
		this.sessionId = sessionId;
		this.lastSessionId = sessionId;
		Logger.info(`setSessionId:`, this.sessionId);
	};

	/** 设置机器人流 */
	private setRobotMembers = (streamData: IAgentJoin): IRobotMembers => {
		let isRobot = streamData.data.user.profile.isRobot;
		let id = streamData.data.id;
		let role = streamData.data.role;
		let userName = streamData.data.user.name;
		return {
			id,
			role,
			isRobot,
			userName
		};
	};

	private updateIsRobot = (clientId: string, isRobot: boolean) => {
		this.agentStreams.forEach(item => {
			if (item.clientId === clientId && isRobot) {
				item.isRobot = true;
			}
		});
	};

	public sessionEnd = () => {
		this.sessionId = '';
		this.invitationId = '';
		this.bizScenarioId = '';
		this.participantId = '';
		this.publicationId = '';
		this.recordingId = '';
		this.roomId = '';
		this.roomToken = '';
		this.clientID = '';
		this.isIMSession = false;

		this.systemRecordPoint = null;
		this.agentRecord = null;
		this.agentStreams = [];
		this.audioStreams = [];
		this.customerStreams = [];
		this.screenStreams = [];
		this.recordStreams = [];
		this.largeStreams = [];
		this.allMediaStream = [];
		this.TTSstream = [];
		this.smallStreams = [];
		this.currentAgentStream = null;

		this.userData = null;
		this.robotMembers = [];
		this.sessionMembers = [];
		this.collectionVariable = [];
		this.transcriptData = [];
		this.responseVariabelData = [];
		this.whiteboardId = '';
		this.pdfWhiteBoardId = '';
		this.TestimonyWriteBoardId = [];
		this.callProgress = 0;
		// this.callProgressTime = null;
		this.callProgressGroups = [];

		this.missCallTimer = 0;
		this.ticketInfo = {
			agentId: '',
			refersh_ticket_time: 0,
			ticket: ''
		};

		this.acceptCallMode = {
			callMediaType: 'video',
			receiveMediaType: 'video',
			microphoneStatus: 'unmute'
		};

		this.recordingPoint = {
			userId: -1,
			userName: '',
			userRole: '',
			recordingId: '',
			content: '',
			timePoint: 0
		};
		this.missCallQuene.clear();
		this.renderedStreamMap.clear();
		this.customerVariableList = [];
		this.businessVariableList = [];
		this.allRoleWihtBusiness = [];
		this.mediaStreamDao.clearAllStream();
		this.setRecordingAlert({ ...this.recordingAlert, systemRecordingId: 0, screenRecordingId: 0, regionalScreenRecordingId: 0 });
	
		
		// this.upgradeData = null;
	};

	public setRoomId(roomId: string) {
		this.roomId = roomId;
	}

	/**
	 * 设置变量数据
	 * @param variables
	 */
	public setCollectionVariable = (variables: ICollectionVariable[]) => {
		this.collectionVariable = variables;
	};

	/**
	 * 获取变量数据
	 * @returns
	 */
	public getCollectionVariable = () => {
		return this.collectionVariable;
	};

	/**
	 * 设置接听模式
	 * @param acceptCallMode
	 */
	public setAcceptCallMode(acceptCallMode: IAcceptCallMode) {
		this.acceptCallMode = acceptCallMode;
	}

	/** 更新呼叫进度 */
	public updateCallProgress(progress: number) {
		this.callProgress = progress;
		// EventEmit.setServiceEventListener({ type: 'progress', event: 'widget' }, { data: this.callProgress, code: 200, message: 'update callProgress success' });
	}

	/** 设置排队分组数据 */
	public setCallProgressGroups(groups: ICallProgressGroups[]) {
		this.callProgressGroups = groups;
		// EventEmit.setServiceEventListener({ type: 'progressGroups', event: 'widget' }, { data: this.callProgressGroups, code: 200, message: 'update callProgressGroups success' });
	}

	/** 设置获取排队数定时器 */
	public setCallProgressTimer(timer: any) {
		this.callProgressTime = timer;
	}

	/** 移除获取排队数定时器 */
	public removeCallProgressTimer() {
		if (!this.callProgressTime) return;
		clearInterval(this.callProgressTime);
		this.callProgressTime = null;
	}

	/** 设置未接听呼叫 */
	public setMissCall(missCall: any) {
		this.missCall = missCall;
	}

	/** 设置随路数据 */
	public setUserCallData(userData: IUserData) {
		this.userData = { ...this.userData, ...userData };
	}

	/**
	 * 设置最大振铃时长
	 * @param time 秒
	 */
	public setMissCallTimer(time: number) {
		this.missCallTimer = time * 1000;
	}

	/** 设置业务场景ID */
	public setBizScenarioId = (bizScenarioId: string) => {
		this.bizScenarioId = bizScenarioId;
		this.lastSceneId = bizScenarioId;
	};

	/** 设置 invitation ID */
	public setInvitationId = (invitationId: string) => {
		this.invitationId = invitationId;
	};

	/** 设置 publicationId ID */
	public setPublicationId = (publicationId: string) => {
		this.publicationId = publicationId;
	};

	/** 设置 participant ID */
	public setParticipantId = (participantId: string) => {
		this.participantId = participantId;
	};

	/** 设置 recordingPoint */
	public setRecordingData = (recordingPoint: IRecordingPoint) => {
		this.recordingPoint = { ...this.recordingPoint, ...recordingPoint };
	};

	/** 设置 room token */
	public setRoomToken = (token: string) => {
		this.roomToken = token;
	};

	/** 设置 client ID */
	public setClientID = (clientID: string) => {
		this.clientID = clientID;
	};

	/** 设置坐席 ticket 信息 */
	public setTicketInfo = (ticketInfo: ITicketInfo) => {
		this.ticketInfo = { ...this.ticketInfo, ...ticketInfo };
	};

	/** 保存 sessions 事件 */
	public saveSessionEventMap(key: ISessionEventKey, fn: void) {
		if (this.eventsMap.has(key)) return;
		this.eventsMap.set(key, fn);
	}

	/** 清除所有 session 事件 */
	public clearSessionEvent() {
		this.eventsMap.forEach((value: void, key) => this.removeSessionEvent(key as ISessionEventKey));
	}

	/** 根据 key 移除 sessions 事件 */
	private removeSessionEvent(key: ISessionEventKey) {
		if (this.eventsMap.has(key)) {
			const fn = this.eventsMap.get(key);
			removeSessionEvent(key, fn);
			this.eventsMap.delete(key);
		}
	}

	public setSessionMembers = (members: IJoinedMembers[]) => {
		this.sessionMembers = filterMembers(members);
		Logger.info(`setSessionMembers:`, this.sessionMembers, members);
		for (let index = 0; index < this.sessionMembers.length; index++) {
			for (let j = index + 1; j < this.sessionMembers.length; j++) {
				if (this.sessionMembers[index].user.name === this.sessionMembers[j].user.name && this.sessionMembers[index].role === 'agent' && this.sessionMembers[j].role === 'agent') {
					this.sessionMembers.splice(index, 1);
					console.log('new sessionMembers', this.sessionMembers);
				}
			}
		}
	};

	public addSessionMembers = (member: IJoinedMembers) => {
		this.sessionMembers = [...this.sessionMembers, memberJoinSession(member)];
		Logger.info(`addSessionMembers:`, this.sessionMembers, memberJoinSession(member));
	};

	public removeSessionMembers = (id: string) => {
		this.sessionMembers = this.sessionMembers.filter(item => item.id !== id);
		Logger.info(`removeSessionMembers:`, this.sessionMembers, id);
	};

	private setMediaStream(stream: IStream) {
		this.mediaStreamDao.setStreams(stream);
		console.log(this.mediaStreamDao.findAllMediaStream(), 'allMediaStream');
	}

	private removeMediaStream(stream: IStream) {
		return this.mediaStreamDao.removeStreamById(stream.id!);
	}
	private removeMediaStreamByClientId(clientId: string) {
		return this.mediaStreamDao.removeStreamByClientId(clientId);
	}

	public saveCurrentAgentStream() {
		const stream = this.mediaStreamDao.findAllMediaStream().find(stream => stream.clientId === this.clientID);
		if (stream) {
			this.currentAgentStream = stream;
		}
	}

	public setRenderedStream(key: string, stream: MediaStream) {
		return this.mediaStreamDao.setRenderedStream(key, stream);
	}

	public removeRenderedStream(key: string) {
		return this.mediaStreamDao.removeRenderedStream(key);
	}

	public getRenderedStreamById(id: string) {
		return this.mediaStreamDao.getRenderedStreamById(id);
	}

	public updateStreamByClientId(id: string, stream: Pick<IStream, 'streamMode'>) {
		return this.mediaStreamDao.updateStreamByClientId(id, stream);
	}

	public getAllMediaSteams() {
		return this.mediaStreamDao.findAllMediaStream();
	}
	public getCustomerMediaStream() {
		return this.mediaStreamDao.findAllCustomerStreams();
	}

	public getAgentMediaStreams() {
		return this.mediaStreamDao.findAllAgentStreams();
	}

	public getSmallStream() {
		return this.mediaStreamDao.findAllSmallStreams();
	}

	public getLargeStream() {
		return this.mediaStreamDao.findAllLargeStreams();
	}

	/** 设置升降级数据 */
	// public setUpgradeData(data: IUpgradeData) {
	// 	this.upgradeData = { ...this.upgradeData, ...data };
	// }

	//设置是否为自动录制
	public setIsAutoSystemRecord(isAutoSystemRecord: boolean) {
		this.isAutoSystemRecord = isAutoSystemRecord;
	}
	// set log level
	public setLogLevel(level: number) {
		Logger.setLevel(level);
	}
}

export default Session;
